#pragma once

#include <type_traits>

#include "../../inc/core/OMIT_MacroDefines.h"

namespace OMIT_NAMESPACE
{
	template<typename Traits>
	class TVert;					// 顶点类型
	template<typename Traits>
	class TEdge;					// 边类型
	template<typename Traits>
	class TFace;					// 面（二维单元）类型
    template<typename Traits>
	class TMesh_H;					// 半边类型（不对外）

	template<typename Traits>
	class TMesh;					// 网格类型

	template<typename _TV, typename _TE, typename _TF, typename _TH>
	struct MeshTraits {
        using TV = _TV;
        using TE = _TE;
        using TF = _TF;
        using TH = _TH;
		using TM = TMesh<MeshTraits>;

        // 要求 Txxxx[X]<MeshTraits> 是 X 的子类
        // 并且 Txxxx 可以基于 Txxx() 进行默认构造
		static constexpr bool IsValid() noexcept {
			return std::is_base_of_v<TVert<MeshTraits>, TV>
				&& std::is_base_of_v<TEdge<MeshTraits>, TE>
				&& std::is_base_of_v<TFace<MeshTraits>, TF>
				&& std::is_base_of_v<TMesh_H<MeshTraits>, TH>
				&& std::is_default_constructible_v<TV>
				&& std::is_default_constructible_v<TE>
				&& std::is_default_constructible_v<TF>
				&& std::is_default_constructible_v<TH>;
		}
	};

    // 计算来自 MeshTraits<V, E, F, H> 的类型

	template<typename Traits>
	using MeshTraits_V = typename Traits::TV;

	template<typename Traits>
	using MeshTraits_E = typename Traits::TE;

	template<typename Traits>
	using MeshTraits_F = typename Traits::TF;

	template<typename Traits>
	using MeshTraits_H = typename Traits::TH;

	template<typename Traits>
	using MeshTraits_M = typename Traits::TM;

    // 指针类型
    //  PtrConst: bool，表示指针是否为常（const）指针
    //  Traits：MeshTraits<V, E, F, H>，网格类型
    //  如果 PtrConst 为真，返回指针类型 const X*
    //  如果 PtrConst 为假，返回指针类型 X*

	template<bool PtrConst, typename Traits>
	using MeshTraits_PV = std::conditional_t<PtrConst, const MeshTraits_V<Traits>*, MeshTraits_V<Traits>*>;

	template<bool PtrConst, typename Traits>
	using MeshTraits_PE = std::conditional_t<PtrConst, const MeshTraits_E<Traits>*, MeshTraits_E<Traits>*>;

	template<bool PtrConst, typename Traits>
	using MeshTraits_PF = std::conditional_t<PtrConst, const MeshTraits_F<Traits>*, MeshTraits_F<Traits>*>;

	template<bool PtrConst, typename Traits>
	using MeshTraits_PH = std::conditional_t<PtrConst, const MeshTraits_H<Traits>*, MeshTraits_H<Traits>*>;
}